home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ABUSESRC.ZIP / AbuseSrc / macabuse / imlib / jmalloc.c < prev    next >
C/C++ Source or Header  |  1997-05-20  |  24KB  |  963 lines

  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include "dprint.hpp"
  5. //#include <new.h>
  6.  
  7. //#ifdef MEM_CHECK
  8. //#define MEM_CLEAR
  9. //#endif
  10.  
  11.  
  12. #ifdef __WATCOMC__
  13. #include "doscall.hpp"
  14. #endif
  15. #include "jmalloc.hpp"
  16. #define uchar unsigned char
  17. #define JM_SMALL_SIZE 128      // above 128 bytes is considered to be a big block and no hashing is done
  18. int alloc_space=ALLOC_SPACE_STATIC;
  19.  
  20. extern void free_up_memory();
  21.  
  22. #ifdef MEM_CHECK
  23. #undef new
  24.  
  25. void *operator new( size_t size, char *file, unsigned long line)
  26. {  
  27.   char buf[200];
  28.   sprintf(buf,"new:: %s:%d",file,line);
  29.   return jmalloc(size,buf);
  30.  
  31.  
  32. long break_mem_point=0;       // can be set in debugger, break mem fun will be called when this address is allocated
  33. void break_mem_fun()
  34. {
  35.   dprintf("memory breakpoint\n");
  36. }
  37. #endif
  38.  
  39. struct memory_node
  40. {
  41.   long size;
  42. #ifdef MEM_CHECK
  43.   char *name;                     // name is allocated on regular heap
  44. #endif                            // because it is used for debugging purposes
  45.                                   // and will probably be run on my linux box with VMM
  46.   memory_node *next;
  47. };
  48.  
  49.  
  50. struct small_block
  51. {  
  52.   unsigned long size;                     // size of blocks...
  53.   unsigned long alloc_list;               // bit field saying weither each block is allocated or not.
  54.   small_block *next;                      // next small block of same size
  55. #ifdef MEM_CHECK
  56.   char *name[32];
  57. #endif 
  58. } ;
  59.  
  60. enum { HI_BLOCK, LOW_BLOCK }; 
  61.  
  62. class block_manager
  63. {
  64.   public :
  65.  
  66.   long block_size;                             // size of this memory_block
  67.   small_block *sblocks[JM_SMALL_SIZE];
  68.   small_block *cblocks[JM_SMALL_SIZE];
  69.   void *addr;
  70.  
  71.   memory_node *sfirst,*slast,
  72.               *cfirst;
  73.   unsigned char block_type;
  74.  
  75.   void init(void *block, long Block_size, uchar type);
  76.   void *static_alloc(long size, char *name);
  77.   void *cache_alloc(long size, char *name);
  78.   void static_free(void *ptr);
  79.   void cache_free(void *ptr);
  80.   long available();
  81.   long allocated();
  82.   long pointer_size(void *ptr);
  83.   void report(FILE *fp);
  84.   void inspect();
  85.  
  86.   int valid_static_ptr(void *ptr);     // only called from within debugger
  87.   int valid_cache_ptr(void *ptr);
  88. } bmanage[5];
  89.  
  90. int bmanage_total=0;
  91.  
  92.  
  93. void inspect_memory()
  94. {
  95.   for (int i=0;i<bmanage_total;i++)
  96.     bmanage[i].inspect();
  97. }
  98.  
  99.  
  100. int block_manager::valid_static_ptr(void *ptr)
  101. {
  102.   void *next=(void *)(*(((long *)ptr)-1));
  103.   
  104.  
  105.   if ((long)next<(long)addr || (long)next>=(long)addr+block_size)
  106.     return 0;
  107.  
  108.   if (((small_block *)next)->size<JM_SMALL_SIZE)  // small allocation
  109.   {
  110.     small_block *s=(small_block *)next;
  111.     if (s->size<=0) return 0;
  112.  
  113.     small_block *c=sblocks[s->size];
  114.     while (c && c!=s) c=c->next;
  115.     if (!c) return 0;
  116.     else return 1;
  117.   }
  118.  
  119.   memory_node *o=(memory_node *)(((char *)ptr)-sizeof(memory_node));
  120.   memory_node *f=sfirst;
  121.   while (f && f!=o) f=f->next;
  122.   if (f) return 1;
  123.   else return 0;
  124. }
  125.  
  126.  
  127. int block_manager::valid_cache_ptr(void *ptr)
  128. {
  129.   void *next=(void *)(*(((long *)ptr)-1));
  130.  
  131.  
  132.   if ((long)next<(long)addr || (long)next>=(long)addr+block_size)
  133.     return 0;
  134.  
  135.   if (next && ((small_block *)next)->size<JM_SMALL_SIZE)  // small allocation
  136.   {
  137.     small_block *s=(small_block *)next;
  138.     if (s->size<=0) return 0;
  139.  
  140.     small_block *c=cblocks[s->size];
  141.     while (c && c!=s) c=c->next;
  142.     if (!c) return 0;
  143.     else return 1;
  144.   }
  145.  
  146.   memory_node *o=(memory_node *)(((char *)ptr)-sizeof(memory_node));
  147.   memory_node *f=cfirst;
  148.   while (f && f!=o) f=f->next;
  149.   if (f) return 1;
  150.   else return 0;
  151.  
  152. }
  153. void small_static_allocation_summary(int &total, int *&static_list, int *&cache_list)
  154. {
  155.   int size=1;
  156.   total=JM_SMALL_SIZE/4;
  157.   static_list=(int *)jmalloc(total*sizeof(int),"small static report");
  158.   cache_list=(int *)jmalloc(total*sizeof(int),"small cache report");
  159.   
  160.   for (;size<total;size++)
  161.   {
  162.     static_list[size]=0;
  163.     cache_list[size]=0;
  164.     int i,x;
  165.     for (i=0;i<bmanage_total;i++)
  166.     {
  167.       small_block *s=bmanage[i].sblocks[size];
  168.       while (s) 
  169.       { 
  170.                 for (x=0;x<32;x++)
  171.                   if (s->alloc_list&(1<<x))
  172.                     static_list[size]++; 
  173.             
  174.                 s=s->next; 
  175.       }
  176.  
  177.       s=bmanage[i].cblocks[size];
  178.       while (s) 
  179.       { 
  180.                 for (x=0;x<32;x++)
  181.                   if (s->alloc_list&(1<<x))
  182.                     cache_list[size]++; 
  183.             
  184.                 s=s->next; 
  185.       }
  186.     }
  187.   }
  188. }
  189.  
  190. void block_manager::inspect()
  191. {
  192.   memory_node *f=sfirst;
  193.   for (;f;f=f->next);               // scan through static big list
  194.  
  195.   int i,bit;
  196.   for (i=0;i<JM_SMALL_SIZE;i++)
  197.   {
  198.     for (small_block *s=sblocks[i];s;s=s->next)
  199.     {
  200.       char *addr=((char *)(s+1));
  201.       bit = 1;
  202.       for (int j=0;j<32;j++)
  203.       {
  204.                 if (s->alloc_list&bit)
  205.                 {
  206.                   void *next=(void *)(*(((long *)addr)));
  207.                   if ((long)next!=(long)s)
  208.                   {
  209.                     dprintf("inspect : bad pointer\n");
  210.                     return ;        
  211.                   }
  212.                 }
  213.                 bit=bit<<1;
  214.                 addr+=s->size+4;
  215.       }    
  216.     }
  217.   }
  218.  
  219. }
  220.  
  221. void block_manager::report(FILE *fp)
  222. {
  223.   fprintf(fp,"************** Block size = %d ***************\n",block_size);
  224.   fprintf(fp,"************** STATIC SPACE ******************\n");
  225.   int i=0;
  226.   memory_node *f=sfirst;
  227.   for (;f;f=f->next,i++)
  228.   {    
  229.     fprintf(fp,"%4d   %p (%d) %4d      ",i,f,((char *)f-(char *)sfirst),f->size);
  230. #ifdef MEM_CHECK
  231.     if (f->size>0)
  232.       fprintf(fp,"%s",f->name);
  233.     else fprintf(fp,"FREE");
  234. #endif
  235.     fprintf(fp,"\n");
  236.   }    
  237.   for (i=0;i<JM_SMALL_SIZE;i++)
  238.   {
  239.     for (small_block *s=sblocks[i];s;s=s->next)
  240.     {      
  241.       fprintf(fp,"*** Small Block size = %d ***\n",i);      
  242.       unsigned long x=0,bit=1;
  243.       char *addr=((char *)(s+1));
  244.       for (int j=0;j<32;j++)
  245.       {
  246.                 fprintf(fp,"%p   ",addr);
  247.                 if (s->alloc_list&bit)
  248.                 {
  249. #ifdef MEM_CHECK
  250.                   fprintf(fp,"%s\n",s->name[j]);
  251. #else
  252.                   fprintf(fp,"allocated\n");
  253. #endif      
  254.                 } else fprintf(fp,"FREE\n");
  255.                 bit=bit<<1;
  256.                 addr+=s->size+4;
  257.       }
  258.     }
  259.   }
  260.  
  261.  
  262.   fprintf(fp,"************** CACHE SPACE ******************\n",block_size);
  263.   i=0;
  264.   for (f=cfirst;f;f=f->next,i++)
  265.   {    
  266.     fprintf(fp,"%4d   %p %4d      ",i,f,f->size);
  267. #ifdef MEM_CHECK
  268.     if (f->size>0)
  269.       fprintf(fp,"%s",f->name);
  270.     else fprintf(fp,"FREE");
  271. #endif
  272.     fprintf(fp,"\n");
  273.   }    
  274.   for (i=0;i<JM_SMALL_SIZE;i++)
  275.   {
  276.     for (small_block *s=cblocks[i];s;s=s->next)
  277.     {      
  278.       fprintf(fp,"*** Small Block size = %d ***\n",i);      
  279.       unsigned long x=0,bit=1;
  280.       char *addr=((char *)(s+1));
  281.       for (int j=0;j<32;j++)
  282.       {
  283.     fprintf(fp,"%p   ",addr);
  284.     if (s->alloc_list&bit)
  285.     {
  286. #ifdef MEM_CHECK
  287.       fprintf(fp,"%s\n",s->name[j]);
  288. #else
  289.       fprintf(fp,"allocated\n");
  290. #endif      
  291.     } else fprintf(fp,"FREE\n");
  292.     bit=bit<<1;
  293.     addr+=s->size+4;
  294.       }
  295.     }
  296.   }
  297. }
  298.  
  299. long block_manager::pointer_size(void *ptr)
  300. {
  301.   void *next=(void *)(*(((long *)ptr)-1));
  302.   if (next>ptr)
  303.     return ((memory_node *)(((char *)ptr)-sizeof(memory_node)))->size;
  304.   else return ((small_block *)next)->size;
  305. }
  306.  
  307. long block_manager::available()
  308. {
  309.   long size=0;
  310.   memory_node *f;
  311.   for (f=sfirst;f;f=f->next)
  312.     if (f->size<0) size-=f->size;
  313.  
  314.   for (f=cfirst;f;f=f->next)
  315.     if (f->size<0) size-=f->size;
  316.   return size;
  317. }
  318.  
  319. long block_manager::allocated()
  320. {
  321.   long size=0;
  322.   memory_node *f;
  323.   for (f=sfirst;f;f=f->next)
  324.     if (f->size>0) size+=f->size;
  325.  
  326.   for (f=cfirst;f;f=f->next)
  327.     if (f->size>0) size+=f->size;
  328.   return size;
  329. }
  330.  
  331. void block_manager::init(void *block, long Block_size, uchar type)
  332. {
  333.   block_size=Block_size;
  334.   addr=block;
  335.   /* 
  336.      I'm padding each block, because I'm comparing pointers against size
  337.      in jfree to determine weither a pointer is too a small object or a large alloc
  338.      and it must always be true that the address of the pointer is > JM_SMALL_SIZE 
  339.      All systems I know start pointer address pretty high, but this is a porting consern.     
  340.   */
  341.   
  342.   slast=sfirst=(memory_node *)(((char *)block)+JM_SMALL_SIZE);   
  343.   sfirst->size=-(block_size-sizeof(memory_node)-JM_SMALL_SIZE);
  344.   sfirst->next=NULL;
  345.   cfirst=NULL;
  346.   memset(sblocks,0,sizeof(sblocks));
  347.   memset(cblocks,0,sizeof(cblocks));
  348.   block_type=type;
  349. }
  350.  
  351. void *block_manager::static_alloc(long size, char *name)
  352. {
  353.   if (size<JM_SMALL_SIZE)
  354.   {
  355.     small_block *s=sblocks[size];
  356.     for (;s && s->alloc_list==0xffffffff;s=s->next);
  357.     if (!s)
  358.     {
  359.       s=(small_block *)static_alloc((size+4)*32+sizeof(small_block),"small_block");
  360.       if (!s) return NULL;   // not enough room for another small block
  361.       s->alloc_list=1;
  362.       s->next=sblocks[size];
  363.       sblocks[size]=s;
  364.       s->size=size;
  365. #ifdef MEM_CHECK
  366.       s->name[0]=strcpy((char *)malloc(strlen(name)+1),name);
  367.       if ((long)s==break_mem_point)
  368.         break_mem_fun();
  369. #endif      
  370.       long *addr=(long *)(((char *)s)+sizeof(small_block));
  371.       *addr=(long)s;
  372.       return (void *)(addr+1);  // return first block
  373.     } else
  374.     {
  375.       int bit=1,i=0,offset=0;
  376.       char *addr=((char *)s)+sizeof(small_block);
  377.       while (1)        // we already know there is a bit free
  378.       {
  379.     if ((s->alloc_list&bit)==0)
  380.     {
  381.       s->alloc_list|=bit;
  382. #ifdef MEM_CHECK
  383.       s->name[i]=strcpy((char *)malloc(strlen(name)+1),name);
  384. #endif           
  385.       *((long *)addr)=(long)s;
  386.  
  387. #ifdef MEM_CHECK
  388.       if ((long)addr==break_mem_point)
  389.             break_mem_fun();
  390. #endif
  391.  
  392.       return (void *)(addr+4);
  393.     }
  394.     i++;
  395.     bit=bit<<1;
  396.     addr+=size+4;
  397.       }      
  398.     }                
  399.   }
  400.  
  401.  
  402.   memory_node *s=sfirst;
  403.   for (;s && -s->size<size;s=s->next);
  404.   if (!s) return NULL;
  405.   s->size=-s->size;
  406.  
  407.   if (s->size-size>sizeof(memory_node)+4)  // is there enough space to split the block?
  408.   {    
  409.     memory_node *p=(memory_node *)((char *)s+sizeof(memory_node)+size);
  410.     if (s==slast)
  411.       slast=p;
  412.     p->size=-(s->size-size-sizeof(memory_node));
  413. #ifdef MEM_CLEAR
  414. //    memset( ((memory_node *)p)+1,0,-p->size);
  415. #endif
  416.     p->next=s->next;
  417.     s->next=p;
  418.     s->size=size;
  419.   }
  420. #ifdef MEM_CHECK
  421.   s->name=strcpy((char *)malloc(strlen(name)+1),name);
  422.  
  423.   if ((long)s==break_mem_point)
  424.     break_mem_fun();
  425.  
  426. #endif
  427.   return (void *)(((char *)s)+sizeof(memory_node));
  428. }
  429.  
  430.  
  431. void *block_manager::cache_alloc(long size, char *name)
  432. {
  433.   if (size<JM_SMALL_SIZE)
  434.   {
  435.     small_block *s=cblocks[size];
  436.     for (;s && s->alloc_list==0xffffffff;s=s->next);
  437.     if (!s)
  438.     {
  439.       s=(small_block *)cache_alloc((size+4)*32+sizeof(small_block),"small_block");
  440.       if (!s) return NULL;   // not enough room for another small block
  441.       s->alloc_list=1;
  442.       s->next=cblocks[size];
  443.       cblocks[size]=s;
  444.       s->size=size;
  445. #ifdef MEM_CHECK
  446.       s->name[0]=strcpy((char *)malloc(strlen(name)+1),name);
  447.  
  448. #endif      
  449.       long *addr=(long *)(((char *)s)+sizeof(small_block));
  450.       *addr=(long)s;
  451. #ifdef MEM_CHECK
  452.       if ((long)s==break_mem_point)
  453.         break_mem_fun();
  454. #endif
  455.       return (void *)(addr+1);  // return first block
  456.     } else
  457.     {
  458.       int bit=1,i=0,offset=0;
  459.       char *addr=((char *)s)+sizeof(small_block);
  460.       while (1)        // we already know there is a bit free
  461.       {
  462.     if ((s->alloc_list&bit)==0)
  463.     {
  464.       s->alloc_list|=bit;
  465. #ifdef MEM_CHECK
  466.       s->name[i]=strcpy((char *)malloc(strlen(name)+1),name);
  467.       if ((long)s==break_mem_point)
  468.         break_mem_fun();
  469. #endif           
  470.       *((long *)addr)=(long)s;
  471.       return (void *)(addr+4);
  472.     }
  473.     i++;
  474.     bit=bit<<1;
  475.     addr+=size+4;
  476.       }      
  477.     }                
  478.   }
  479.  
  480.  
  481.   memory_node *clast=NULL;
  482.   memory_node *s=cfirst;
  483.   for (;s && -s->size<size;s=s->next) clast=s;
  484.   if (!s) // no current cache space for object, see if we can enlarge the cache space
  485.   {
  486.     long size_avail=-slast->size;
  487.     size_avail-=sizeof(memory_node);
  488.  
  489.     if (slast->size>0 || size_avail<size) // not enough space
  490.       return NULL;
  491.     else
  492.     {
  493.       slast->size+=size+sizeof(memory_node);
  494.       memory_node *nc=(memory_node *)(((char *)(slast)) + (-slast->size+sizeof(memory_node)));
  495.       
  496.       nc->next=NULL;
  497.       nc->size=size;
  498. #ifdef MEM_CHECK
  499.       nc->name=strcpy((char *)malloc(strlen(name)+1),name);      
  500.       if ((long)nc==break_mem_point)
  501.         break_mem_fun();
  502. #endif      
  503.       if (!clast)
  504.         cfirst=nc;
  505.       else clast->next=nc;
  506.       return (void *)(((char *)nc)+sizeof(memory_node));
  507.     }
  508.   }
  509.  
  510.  
  511.   s->size=-s->size;
  512.  
  513.   if (s->size-size>sizeof(memory_node)+4)  // is there enough space to split the block?
  514.   {
  515.     memory_node *p=s;    // store this position
  516.     long psize=s->size-size-sizeof(memory_node);
  517.     s=(memory_node *)(((char *)s)+psize+sizeof(memory_node));
  518.     p->size=-psize;
  519.     s->next=p;
  520.     s->size=size;
  521.     if (cfirst==p) cfirst=s;
  522.     else clast->next=s;
  523.   }
  524. #ifdef MEM_CHECK
  525.   s->name=strcpy((char *)malloc(strlen(name)+1),name);
  526.   if ((long)s==break_mem_point)
  527.     break_mem_fun();
  528. #endif
  529.   return (void *)(((char *)s)+sizeof(memory_node));
  530. }
  531.  
  532.  
  533. /************************** CACHE FREE ****************************/
  534. /*    should be called to free a pointer in the cache heap        */
  535. /*    i.e. end of the heap                                        */
  536. /******************************************************************/
  537. void block_manager::cache_free(void *ptr)
  538. {
  539.   // see if this was a small_block allocation
  540.   void *next=(void *)(*(((long *)ptr)-1));
  541.   if (next && ((small_block *)next)->size<JM_SMALL_SIZE)  // small allocation
  542.   {
  543.     small_block *s=(small_block *)next;
  544.     if (s->size<=0)
  545.     {
  546.       dprintf("jfree : bad pointer\n");
  547.       return ;
  548.     }
  549.  
  550.     int field=(((char *)ptr)-((char *)s)-sizeof(small_block))/(s->size+4);
  551. #ifdef MEM_CHECK
  552.     free(s->name[field]);
  553. #endif
  554.     s->alloc_list&=(0xffffffff-(1<<field));
  555.     if (s->alloc_list==0)
  556.     {
  557.       small_block *l=NULL;
  558.       small_block *n=cblocks[s->size];
  559.       for (;n!=s;n=n->next) l=n;
  560. #ifdef MEM_CHECK
  561.       if (!n) 
  562.       { dprintf("Free small block error\n"); }
  563. #endif
  564.       if (!l)
  565.       cblocks[s->size]=s->next;
  566.       else l->next=s->next;
  567.       cache_free(s);
  568.     }      
  569.   } else
  570.   {
  571.     memory_node *o=(memory_node *)(((char *)ptr)-sizeof(memory_node)),*last=NULL;
  572.     memory_node *n=cfirst;
  573.     for (;n && n!=o;n=n->next) last=n;
  574. #ifdef MEM_CHECK
  575.     if (!n) 
  576.     { dprintf("Free cached big block error\n"); }
  577.     free(o->name);
  578. #endif
  579.     
  580.     if (last && last->size<0)   // can we add into last block
  581.     {
  582.       memory_node *prev=NULL;
  583.       for (memory_node *n=cfirst;n && n!=last;n=n->next) prev=n;   // find previous to last pointer
  584.       if (prev)
  585.         prev->next=o;
  586.       else cfirst=o;
  587.  
  588.       o->size=last->size-o->size-sizeof(memory_node);
  589.       last=prev;
  590.     } else o->size=-o->size;
  591.     
  592.     if (!o->next)           // if no next block, then we should add back into static memory
  593.     {
  594.       if (last) last->next=NULL;  // unlink from cache chain
  595.       else cfirst=NULL;
  596.  
  597.       if (slast->size>0)    // if last static is allocated then create a new free static at end of list
  598.       {
  599.     slast->next=o;
  600.     slast=o;
  601.       } else      
  602.     slast->size+=o->size-sizeof(memory_node);  // else just increase the size of last block
  603.     } else if (o->next->size<0)   // see if we can add into next block
  604.     {
  605.       o->next->size+=o->size-sizeof(memory_node);
  606.       if (last)      
  607.     last->next=o->next;
  608.       else
  609.         cfirst=o->next;
  610.     }
  611.   }  
  612. }
  613.  
  614.  
  615.  
  616. /************************** STATIC FREE ***************************/
  617. /*    should be called to free a pointer in the static heap       */
  618. /*    i.e. begining of the heap                                   */
  619. /******************************************************************/
  620. void block_manager::static_free(void *ptr)
  621. {
  622.   // see if this was a small_block allocation
  623.   void *next=(void *)(*(((long *)ptr)-1));
  624.   if (next && next<ptr)  // small allocation
  625.   {
  626.     small_block *s=(small_block *)next;
  627.     if (s->size<=0)
  628.     {
  629.       dprintf("jfree : bad pointer\n");
  630.       return ;
  631.     }
  632. #ifdef MEM_CLEAR
  633.     memset(ptr,0,s->size);
  634. #endif
  635.  
  636.     int field=(((char *)ptr)-((char *)s)-sizeof(small_block))/(s->size+4);
  637. #ifdef MEM_CHECK
  638.     free(s->name[field]);
  639. #endif
  640.     s->alloc_list&=(0xffffffff-(1<<field));
  641.     if (s->alloc_list==0)
  642.     {
  643.       small_block *l=NULL;
  644.       small_block *n=sblocks[s->size];
  645.       for (;n!=s;n=n->next) l=n;
  646. #ifdef MEM_CHECK
  647.       if (!n) { dprintf("Free static small block error\n"); }
  648. #endif
  649.       if (!l)
  650.       sblocks[s->size]=s->next;
  651.       else l->next=s->next;
  652.       static_free(s);
  653.     }      
  654.   } else
  655.   {
  656.     memory_node *o=(memory_node *)(((char *)ptr)-sizeof(memory_node)),*last=NULL;
  657. #ifdef MEM_CHECK
  658.     free(o->name);
  659. #endif
  660. #ifdef MEM_CLEAR
  661.     memset(ptr,0,o->size);
  662. #endif
  663.  
  664.     if (o->next && o->next->size<0)   // see if we can add into next block
  665.     {
  666.       if (o->next==slast)
  667.         slast=o;
  668.       o->size+=-o->next->size+sizeof(memory_node);
  669.       o->next=o->next->next;
  670.     }
  671.  
  672.     memory_node *n=sfirst;
  673.     for (;n && n!=o;n=n->next) last=n;
  674. #ifdef MEM_CHECK
  675.     if (!n) { dprintf("Free static big block error\n"); }
  676. #endif
  677.     
  678.     if (last && last->size<0)
  679.     {
  680.       if (o==slast) slast=last;
  681.       last->next=o->next;
  682.       last->size-=o->size+sizeof(memory_node);    
  683.     } else o->size=-o->size;            
  684.   }  
  685. }
  686.  
  687.  
  688. void jmalloc_uninit()
  689. {
  690.   for (int i=0;i<bmanage_total;i++)
  691.   {
  692.     switch (bmanage[i].block_type)
  693.     {
  694.       case HI_BLOCK : 
  695.       { free(bmanage[i].addr); } break;
  696. #ifdef __WATCOMC__      
  697.       case LOW_BLOCK :
  698.       { free_low_memory(bmanage[i].addr); } break;
  699. #endif      
  700.     }
  701.   }
  702.   bmanage_total=0;
  703. }
  704.  
  705. void jmem_cleanup(int ret, void *arg)
  706. { jmalloc_uninit(); }
  707.  
  708.  
  709. //int jmalloc_max_size=3072000;
  710. int jmalloc_max_size=4096000;
  711. int jmalloc_min_low_size=0x1000;
  712. char *not_enough_total_memory_message="Memory manager : Sorry you do not have enough memory available to\n"
  713.                                        "                 run this program.\n"
  714.                        "    DOS users  : Remove any TSR's and device drivers you can.\n"
  715.                        "    UNIX users : Do you have a swapfile/partition setup?\n";
  716. char *not_enough_low_memory_message="Memory Manager : Not enough low memory available (%d : need %d)\n"
  717.                                    "  Suggestions...\n"
  718.                    "    - make a boot disk\n"
  719.                    "    - remove TSR's  & drivers not needed by ABUSE\n"
  720.                    "    - add memory to your system\n";
  721.  
  722. void jmalloc_init(long min_size)
  723. {
  724.   if (bmanage_total)
  725.     dprintf("warning : jmalloc_init called twice\n");
  726.   else
  727.   {
  728. //    exit_proc(jmem_cleanup,jmalloc_uninit);          // make sure memory gets freed up on exit
  729.     void *mem;
  730.  
  731. #ifdef __MAC__
  732.     long size=jmalloc_max_size-0x10000;
  733.     for (mem=NULL;!mem && size>0x10000;)
  734.     {
  735.       mem=malloc(size+0x10000);
  736.       if (!mem) size-=0x100;        
  737.     }
  738.     free(mem);
  739.     mem = malloc(size);
  740. #else
  741.     long size=jmalloc_max_size;
  742.     for (mem=NULL;!mem && size>0x4000;)
  743.     {
  744.       mem=malloc(size);
  745.       if (!mem) size-=0x100;        
  746.     }
  747. #endif
  748.     if (mem)
  749.     {
  750.             bmanage[bmanage_total].init(mem,size,HI_BLOCK);
  751.             bmanage_total++;      
  752.             dprintf("Added himem block (%d bytes)\n",size);
  753.     }
  754.  
  755. /*    bmanage[bmanage_total].init(malloc(2039552),2039552,HI_BLOCK);
  756.     bmanage_total++;      
  757.     bmanage[bmanage_total].init(malloc(150224),150224,HI_BLOCK);
  758.     bmanage_total++;      */
  759.  
  760.  
  761.  
  762. #ifdef __WATCOMC__
  763.     if (size!=jmalloc_max_size)
  764.     {
  765.       do
  766.       {
  767.                 size=low_memory_available();
  768.                 if (size>jmalloc_min_low_size+0x1000)              // save 64K for misc low memory needs
  769.                 {
  770.                   bmanage[bmanage_total].init(alloc_low_memory(size-jmalloc_min_low_size-0x1000),size-jmalloc_min_low_size-0x1000,LOW_BLOCK);
  771.                   bmanage_total++; 
  772.                   dprintf("Added low memory block (%d bytes)\n",size);
  773.                 }
  774.       } while (size>jmalloc_min_low_size+0x1000);
  775.       if (size<jmalloc_min_low_size)
  776.       {
  777.                 dprintf(not_enough_low_memory_message,size,jmalloc_min_low_size);
  778.                 exit(0);
  779.       }
  780.     }
  781. #endif
  782.  
  783.  
  784.     dprintf("Memory avialable : %d\n",j_available());
  785.     if (j_available()<min_size)
  786.     {
  787.       dprintf(not_enough_total_memory_message);
  788.       exit(0);
  789.     }
  790.  
  791.   }
  792. }
  793.  
  794.  
  795. long j_available()
  796. {
  797.   long size=0;
  798.   for (int i=0;i<bmanage_total;i++) 
  799.     size+=bmanage[i].available();
  800.   return size;
  801. }
  802.  
  803. long j_allocated()
  804. {
  805.   long size=0;
  806.   for (int i=0;i<bmanage_total;i++) 
  807.     size+=bmanage[i].allocated();
  808.   return size;
  809. }
  810.  
  811. int alloc_instance=0;
  812.  
  813. void *jmalloc(long size, char *name)
  814. {
  815.  
  816.  
  817.   if (!bmanage_total)
  818. #if 0
  819.       return malloc(size);
  820. #else
  821.         jmalloc_init(0x150000);
  822. #endif
  823.   size=(size+3)&(0xffffffff-3);
  824.  
  825.  
  826. #ifdef MEM_CHECK
  827.   char name2[100];
  828.   sprintf(name2,"%s : %d\n",name,alloc_instance);
  829.   alloc_instance++;
  830. #else
  831.   char *name2=name;
  832. #endif
  833.  
  834.   do
  835.   {
  836.     for (int i=0;i<bmanage_total;i++)
  837.     {
  838.       void *a;
  839.       if (alloc_space==ALLOC_SPACE_STATIC)
  840.         a=bmanage[i].static_alloc(size,name2);
  841.       else
  842.         a=bmanage[i].cache_alloc(size,name2);
  843.       if (a) return a;
  844.     }
  845.     free_up_memory();
  846.   } while (1);  
  847. }
  848.  
  849. void jfree(void *ptr)
  850. {
  851.   if (!bmanage_total) 
  852.   { 
  853.     free(ptr); 
  854.     return ; 
  855.   }
  856.   for (int i=0;i<bmanage_total;i++)
  857.     if (ptr>=(void *)bmanage[i].sfirst)  // is the pointer in this block?
  858.     {
  859.       if (ptr<=(void *)bmanage[i].slast)  // is it in static space?
  860.       {
  861.     bmanage[i].static_free(ptr);
  862.     return ;
  863.       } else if (ptr<=(void *)(((char *)bmanage[i].sfirst)+bmanage[i].block_size))  // or cache space?
  864.       {
  865.     bmanage[i].cache_free(ptr);
  866.     return ;
  867.       }
  868.     }
  869.   
  870.   dprintf("jfree : bad pointer\n");
  871. }
  872.  
  873.  
  874. void *jrealloc(void *ptr, long size, char *name)
  875. {  
  876.   if (!ptr) return jmalloc(size,name);
  877.   if (!bmanage_total) { return realloc(ptr,size); }
  878.  
  879.   if (size==0) { jfree(ptr); return NULL; }
  880.  
  881.   long old_size=0;
  882.   for (int i=0;i<bmanage_total;i++)
  883.     if (ptr>=(void *)bmanage[i].sfirst && 
  884.     ptr<=(void *)(((char *)bmanage[i].sfirst)+bmanage[i].block_size))
  885.     {
  886.       old_size=bmanage[i].pointer_size(ptr);  
  887.       if (ptr<=(void *)bmanage[i].slast)
  888.       {
  889.     int sp=alloc_space; sp=ALLOC_SPACE_STATIC;
  890.     void *nptr=jmalloc(size,name);
  891.     if (size>old_size)
  892.       memcpy(nptr,ptr,old_size);
  893.      else memcpy(nptr,ptr,size);
  894.     bmanage[i].static_free(ptr);
  895.     alloc_space=sp;
  896.     return nptr;
  897.       } else
  898.       {
  899.     int sp=alloc_space; sp=ALLOC_SPACE_CACHE;
  900.     void *nptr=jmalloc(size,name);
  901.     if (size>old_size)
  902.       memcpy(nptr,ptr,old_size);
  903.     else memcpy(nptr,ptr,size);
  904.     bmanage[i].cache_free(ptr);
  905.     alloc_space=sp;
  906.     return nptr;
  907.       }
  908.     }
  909.   dprintf("jrealloc : bad pointer\n");
  910.   return NULL;
  911. }
  912.  
  913. void dmem_report()
  914. {
  915.   mem_report("debug.mem");
  916. }
  917.  
  918.  
  919. void mem_report(char *filename)
  920. {
  921.   FILE *fp=fopen(filename,"wb");
  922.   for (int i=0;i<bmanage_total;i++)
  923.     bmanage[i].report(fp);
  924.   fclose(fp);
  925. }
  926.  
  927. void *operator new( size_t size)
  928. {  
  929.   return jmalloc(size,"::new object");
  930.  
  931. void operator delete(void *ptr)
  932. {
  933.   jfree(ptr);
  934. }
  935.  
  936.  
  937. long small_ptr_size(void *ptr)
  938. {
  939.   return ((small_block *)(((long *)ptr)[-1]))->size;
  940. }
  941.  
  942.  
  943. int valid_ptr(void *ptr)
  944. {
  945.   if (!bmanage_total) { return 0; }
  946.   for (int i=0;i<bmanage_total;i++)
  947.     if (ptr>=(void *)bmanage[i].sfirst)  // is the pointer in this block?
  948.     {
  949.       if (ptr<=(void *)bmanage[i].slast)  // is it in static space?
  950.       {
  951.     return bmanage[i].valid_static_ptr(ptr);
  952.       } else if (ptr<=(void *)(((char *)bmanage[i].sfirst)+bmanage[i].block_size))  // or cache space?
  953.       {
  954.     return bmanage[i].valid_cache_ptr(ptr);
  955.       }
  956.     }
  957.  
  958.   return 0;
  959. }
  960.  
  961.